﻿using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.UI.CanvasScaler;

public class BoardDisplay : MonoBehaviour
{
    Board m_Board;
    public Team m_ViewPoint; // 以哪一方的时点

    Dictionary<Vector2Int, CellDisplay> m_CellDisplays;
    Dictionary<UnitBase, UnitDisplay> m_UnitDisplays;

    public Scenario m_DebugScenario;
    public ActionQueuePanel m_ActionQueuePanel;

    CameraController m_CameraController;
    public float m_CameraBoardEdge = 2f;
    void Awake()
    {
        MessageManager.Instance.AddListener(ClientEvent.Refresh, RefreshBoard);
        MessageManager<UnitBase>.Instance.AddListener(ClientEvent.UnitStart, OnUnitStart);
        MessageManager<UnitBase>.Instance.AddListener(ClientEvent.UnitEnd, OnUnitEnd);
        MessageManager<GameObject>.Instance.AddListener(ClientEvent.ClickObject, OnClickObject);
    }
    public void Start()
    {
        m_CameraController = Camera.main.GetComponent<CameraController>();
        if (m_DebugScenario != null)
        {
            m_Board = new Board();
            m_Board.InitBoard(m_DebugScenario);
            Init(m_Board);
        }
    }
    private void OnDestroy()
    {
        MessageManager.Instance.RemoveListener(ClientEvent.Refresh, RefreshBoard);
        MessageManager<UnitBase>.Instance.RemoveListener(ClientEvent.UnitStart, OnUnitStart);
        MessageManager<UnitBase>.Instance.RemoveListener(ClientEvent.UnitEnd, OnUnitEnd);
        MessageManager<GameObject>.Instance.RemoveListener(ClientEvent.ClickObject, OnClickObject);
    }

    public void CalculateCameraRestrainParam()
    {
        Camera cam = Camera.main;
        Vector3 lowleft = cam.ViewportToWorldPoint(Vector3.zero);
        Vector3 upright = cam.ViewportToWorldPoint(Vector3.one);
        float camHalfWidth = (upright.x - lowleft.x) * 0.5f;
        float camHalfHeight = (upright.y - lowleft.y) * 0.5f;
        m_CameraController.maxX = m_Board.Width - 1f - camHalfWidth + m_CameraBoardEdge;
        m_CameraController.minX = camHalfWidth - m_CameraBoardEdge;
        if (m_CameraController.minX > m_CameraController.maxX)
        {
            m_CameraController.minX = m_CameraController.maxX = (m_Board.Width - 1f) * 0.5f;
        }
        m_CameraController.maxY = m_Board.Height - 1f - camHalfHeight + m_CameraBoardEdge;
        m_CameraController.minY = camHalfHeight - m_CameraBoardEdge;
        if (m_CameraController.minY > m_CameraController.maxY)
        {
            m_CameraController.minY = m_CameraController.maxY = (m_Board.Height - 1f) * 0.5f;
        }
    }

    public void Init(Board board)
    {
        m_Board = board;
        

        m_CellDisplays = new Dictionary<Vector2Int, CellDisplay>();
        m_UnitDisplays = new Dictionary<UnitBase, UnitDisplay>();

        foreach (var item in m_Board.BoardMap)
        {
            Vector2Int pos = item.Key;
            Cell cell = item.Value;

            GameObject cellPrefab = ResourceManager<GameObject>.Instance.LoadResource($"prefabs/cells/{cell.Type.ToString()}");
            GameObject cellGo = GameObject.Instantiate(cellPrefab, transform);
            CellDisplay cellDisplay = cellGo.GetComponent<CellDisplay>();
            cellDisplay.Init(cell);

            m_CellDisplays.Add(pos, cellDisplay);

            if (cell.Unit != null)
            {
                UnitBase unit = cell.Unit;
                GameObject unitPrefab = ResourceManager<GameObject>.Instance.LoadResource($"prefabs/units/{unit.type.ToString()}_{unit.team.ToString()}");
                GameObject unitGo = GameObject.Instantiate(unitPrefab, transform);
                UnitDisplay unitDisplay = unitGo.GetComponent<UnitDisplay>();
                unitDisplay.Init(unit);
                unitDisplay.m_BoardDisplay = this;
                m_UnitDisplays.Add(unit, unitDisplay);
            }
        }
        board.Update();
        board.StartPhase();
        RefreshBoard();
        m_ActionQueuePanel.SetActionQueueDisplay(board.ActionQueue, m_ViewPoint);
    }

    public void Update()
    {
        if (m_Board == null) return;

        CalculateCameraRestrainParam();

        if (Input.GetKeyDown(KeyCode.F5))
        {
            MessageManager.Instance.Invoke("Refresh");
        }
    }

    public void ClearHighlights()
    {
        foreach (CellDisplay cellDisplay in m_CellDisplays.Values)
        {
            cellDisplay.SetHighlight(false, false);
        }
    }
    public void RefreshBoard()
    {
        foreach (CellDisplay cellDisplay in m_CellDisplays.Values)
        {
            cellDisplay.SetVisible(m_ViewPoint);
        }
        foreach (UnitDisplay unitDisplay in m_UnitDisplays.Values)
        {
            unitDisplay.Refresh(m_ViewPoint);
        }
    }

    public void OnUnitStart(UnitBase unit)
    {
        UnitDisplay unitDisplay = m_UnitDisplays[unit];
        unitDisplay.OnStartAction();
    }
    public void OnUnitEnd(UnitBase unit)
    {
        UnitDisplay unitDisplay = m_UnitDisplays[unit];
        unitDisplay.OnEndAction();
    }
    public void OnClickObject(GameObject go)
    {
        
    }
    
}